package com.epam.ws.anatomist.message;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class PropertiesGenerator
{

	public static final String DATE_KEY = "Date";

	public static final String DELTA = "delta(";

	public static final String GENERATE_COMMAND_REGEXP = "generate\\((.)\\)";

	public static final String GENERATE_UUID_COMMAND = "generateUUID()";

	public static final Pattern GENERATE_NUMBER_PATTERN = Pattern.compile(GENERATE_COMMAND_REGEXP);

	public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("YYYY-MM-DD'T'hh:mm:ss");

	public static void scanPropertiesAndGenerate(Properties properties)
	{
		if (properties == null)
		{
			return;
		}
		putDynamicDateInProperties(properties, DATE_FORMAT);
		putGeneratedNumbersInProperties(properties);

	}

	public static void putDynamicDateInProperties(Properties properties, SimpleDateFormat dateFormat)
	{
		if (properties == null)
		{
			return;
		}
		Enumeration<Object> keys = properties.keys();
		List<String> dateDeltaList = new ArrayList<String>();
		while (keys.hasMoreElements())
		{
			String key = (String) keys.nextElement();
			if (key.contains(DATE_KEY))
			{
				dateDeltaList.add(key);
			}
		}
		for (String dateDeltaProperty : dateDeltaList)
		{
			if (properties.containsKey(dateDeltaProperty))
			{
				String dateFromProps = properties.getProperty(dateDeltaProperty);
				if (dateFromProps != null)
				{
					String preparedDate = convertDateDelta(dateFromProps, dateFormat);
					properties.setProperty(dateDeltaProperty, preparedDate);
				}
			}
		}
	}

	public static String generateStringDateFromDelta(int delta, SimpleDateFormat dateFormat)
	{
		Calendar calendar = new GregorianCalendar();
		calendar.set(Calendar.DAY_OF_MONTH, calendar.get(Calendar.DAY_OF_MONTH) + delta);
		String preparedDate = dateFormat.format(calendar.getTime());
		return preparedDate;
	}

	public static String convertDateDelta(String originalValue, SimpleDateFormat dateFormat)
	{
		if (originalValue.startsWith(DELTA))
		{
			String deltaValue = originalValue.substring(DELTA.length(), originalValue.length() - 1);
			int delta = Integer.valueOf(deltaValue);
			return generateStringDateFromDelta(delta, dateFormat);
		}
		return originalValue;
	}

	public static void putGeneratedNumbersInProperties(Properties properties)
	{
		if (properties == null)
		{
			return;
		}
		int length = 0;
		String propertyValue;
		Enumeration<Object> keys = properties.keys();
		while (keys.hasMoreElements())
		{
			String key = (String) keys.nextElement();
			propertyValue = properties.getProperty(key);
			if (propertyValue != null)
			{
				propertyValue = propertyValue.trim();
				Matcher m = GENERATE_NUMBER_PATTERN.matcher(propertyValue);
				if (m.find())
				{
					try
					{
						length = Integer.valueOf(m.group(1).trim());
					}
					catch (NumberFormatException e)
					{
						throw new RuntimeException(
						        "You must provide Integer number between braces in 'generate()' (e.g. generate(5))", e);
					}
					properties.put(key,
					        propertyValue.replaceAll(GENERATE_COMMAND_REGEXP, generateNumberAsString(length)));
				}
				if (GENERATE_UUID_COMMAND.equals(propertyValue))
				{
					propertyValue = UUID.randomUUID().toString();
					properties.put(key, propertyValue);
				}
			}
		}
	}

	public static String generateNumberAsString(int length)
	{
		return String.valueOf(generateNumber(length));
	}

	public static int generateNumber(int length)
	{
		int max = (int) Math.pow(10, length) - 1;
		int min = (int) Math.pow(10, length - 1);
		int randomNumber = new Random().nextInt(max - min + 1) + min;
		return randomNumber;
	}

}
